home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 May / maximum-cd-2009-05.iso / DiscContents / Firefox Setup 3.0.6.exe / nonlocalized / components / nsBrowserGlue.js < prev    next >
Encoding:
Text File  |  2009-01-19  |  31.6 KB  |  849 lines

  1. //@line 39 "e:\fx19rel\WINNT_5.2_Depend\mozilla\browser\components\nsBrowserGlue.js"
  2.  
  3. const Ci = Components.interfaces;
  4. const Cc = Components.classes;
  5. const Cr = Components.results;
  6. const Cu = Components.utils;
  7.  
  8. Cu.import("resource://gre/modules/XPCOMUtils.jsm");
  9. Cu.import("resource:///modules/distribution.js");
  10.  
  11. const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
  12.  
  13. // Check to see if bookmarks need backing up once per
  14. // day on 1 hour idle.
  15. const BOOKMARKS_ARCHIVE_IDLE_TIME = 60 * 60;
  16.  
  17. // Backup bookmarks once every 24 hours.
  18. const BOOKMARKS_ARCHIVE_INTERVAL = 86400 * 1000;
  19.  
  20. // Factory object
  21. const BrowserGlueServiceFactory = {
  22.   _instance: null,
  23.   createInstance: function (outer, iid) 
  24.   {
  25.     if (outer != null)
  26.       throw Components.results.NS_ERROR_NO_AGGREGATION;
  27.     return this._instance == null ?
  28.       this._instance = new BrowserGlue() : this._instance;
  29.   }
  30. };
  31.  
  32. // Constructor
  33.  
  34. function BrowserGlue() {
  35.   this._init();
  36. }
  37.  
  38. BrowserGlue.prototype = {
  39.   __prefs: null,
  40.   get _prefs() {
  41.     if (!this.__prefs)
  42.       this.__prefs = Cc["@mozilla.org/preferences-service;1"].
  43.                      getService(Ci.nsIPrefBranch);
  44.     return this.__prefs;
  45.   },
  46.  
  47.   _saveSession: false,
  48.  
  49.   _setPrefToSaveSession: function()
  50.   {
  51.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  52.                      getService(Ci.nsIPrefBranch);
  53.     prefBranch.setBoolPref("browser.sessionstore.resume_session_once", true);
  54.   },
  55.  
  56.   // nsIObserver implementation 
  57.   observe: function(subject, topic, data) 
  58.   {
  59.     switch(topic) {
  60.       case "xpcom-shutdown":
  61.         this._dispose();
  62.         break;
  63.       case "quit-application": 
  64.         this._onProfileShutdown();
  65.         break;
  66.       case "prefservice:after-app-defaults":
  67.         this._onAppDefaults();
  68.         break;
  69.       case "final-ui-startup":
  70.         this._onProfileStartup();
  71.         break;
  72.       case "sessionstore-windows-restored":
  73.         this._onBrowserStartup();
  74.         break;
  75.       case "browser:purge-session-history":
  76.         // reset the console service's error buffer
  77.         const cs = Cc["@mozilla.org/consoleservice;1"].
  78.                    getService(Ci.nsIConsoleService);
  79.         cs.logStringMessage(null); // clear the console (in case it's open)
  80.         cs.reset();
  81.         break;
  82.       case "quit-application-requested":
  83.         this._onQuitRequest(subject, data);
  84.         break;
  85.       case "quit-application-granted":
  86.         if (this._saveSession) {
  87.           this._setPrefToSaveSession();
  88.         }
  89.         break;
  90.       case "session-save":
  91.         this._setPrefToSaveSession();
  92.         subject.QueryInterface(Ci.nsISupportsPRBool);
  93.         subject.data = true;
  94.         break;
  95.       case "idle":
  96.         if (this.idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) {
  97.           // Back up bookmarks.
  98.           this._archiveBookmarks();
  99.         }
  100.         break;
  101.     }
  102.   }, 
  103.  
  104.   // initialization (called on application startup) 
  105.   _init: function() 
  106.   {
  107.     // observer registration
  108.     const osvr = Cc['@mozilla.org/observer-service;1'].
  109.                  getService(Ci.nsIObserverService);
  110.     osvr.addObserver(this, "quit-application", false);
  111.     osvr.addObserver(this, "xpcom-shutdown", false);
  112.     osvr.addObserver(this, "prefservice:after-app-defaults", false);
  113.     osvr.addObserver(this, "final-ui-startup", false);
  114.     osvr.addObserver(this, "sessionstore-windows-restored", false);
  115.     osvr.addObserver(this, "browser:purge-session-history", false);
  116.     osvr.addObserver(this, "quit-application-requested", false);
  117.     osvr.addObserver(this, "quit-application-granted", false);
  118.     osvr.addObserver(this, "session-save", false);
  119.   },
  120.  
  121.   // cleanup (called on application shutdown)
  122.   _dispose: function() 
  123.   {
  124.     // observer removal 
  125.     const osvr = Cc['@mozilla.org/observer-service;1'].
  126.                  getService(Ci.nsIObserverService);
  127.     osvr.removeObserver(this, "quit-application");
  128.     osvr.removeObserver(this, "xpcom-shutdown");
  129.     osvr.removeObserver(this, "prefservice:after-app-defaults");
  130.     osvr.removeObserver(this, "final-ui-startup");
  131.     osvr.removeObserver(this, "sessionstore-windows-restored");
  132.     osvr.removeObserver(this, "browser:purge-session-history");
  133.     osvr.removeObserver(this, "quit-application-requested");
  134.     osvr.removeObserver(this, "quit-application-granted");
  135.     osvr.removeObserver(this, "session-save");
  136.   },
  137.  
  138.   _onAppDefaults: function()
  139.   {
  140.     // apply distribution customizations (prefs)
  141.     // other customizations are applied in _onProfileStartup()
  142.     var distro = new DistributionCustomizer();
  143.     distro.applyPrefDefaults();
  144.   },
  145.  
  146.   // profile startup handler (contains profile initialization routines)
  147.   _onProfileStartup: function() 
  148.   {
  149.     this.Sanitizer.onStartup();
  150.     // check if we're in safe mode
  151.     var app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
  152.               QueryInterface(Ci.nsIXULRuntime);
  153.     if (app.inSafeMode) {
  154.       var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  155.                getService(Ci.nsIWindowWatcher);
  156.       ww.openWindow(null, "chrome://browser/content/safeMode.xul", 
  157.                     "_blank", "chrome,centerscreen,modal,resizable=no", null);
  158.     }
  159.  
  160.     // initialize Places
  161.     this._initPlaces();
  162.  
  163.     // apply distribution customizations
  164.     // prefs are applied in _onAppDefaults()
  165.     var distro = new DistributionCustomizer();
  166.     distro.applyCustomizations();
  167.  
  168.     // handle any UI migration
  169.     this._migrateUI();
  170.  
  171.     const osvr = Cc['@mozilla.org/observer-service;1'].
  172.                  getService(Ci.nsIObserverService);
  173.     osvr.notifyObservers(null, "browser-ui-startup-complete", "");
  174.   },
  175.  
  176.   // profile shutdown handler (contains profile cleanup routines)
  177.   _onProfileShutdown: function() 
  178.   {
  179.     this._shutdownPlaces();
  180.     this.idleService.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
  181.     this.Sanitizer.onShutdown();
  182.   },
  183.  
  184.   // Browser startup complete. All initial windows have opened.
  185.   _onBrowserStartup: function()
  186.   {
  187.     // Show about:rights notification, if needed.
  188.     if (this._shouldShowRights())
  189.       this._showRightsNotification();
  190.  
  191.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  192.                      getService(Ci.nsIPrefBranch);
  193.     // If new add-ons were installed during startup open the add-ons manager.
  194.     if (prefBranch.prefHasUserValue(PREF_EM_NEW_ADDONS_LIST)) {
  195.       var args = Cc["@mozilla.org/supports-array;1"].
  196.                  createInstance(Ci.nsISupportsArray);
  197.       var str = Cc["@mozilla.org/supports-string;1"].
  198.                 createInstance(Ci.nsISupportsString);
  199.       str.data = "";
  200.       args.AppendElement(str);
  201.       var str = Cc["@mozilla.org/supports-string;1"].
  202.                 createInstance(Ci.nsISupportsString);
  203.       str.data = prefBranch.getCharPref(PREF_EM_NEW_ADDONS_LIST);
  204.       args.AppendElement(str);
  205.       const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
  206.       const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
  207.       var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  208.                getService(Ci.nsIWindowWatcher);
  209.       ww.openWindow(null, EMURL, "_blank", EMFEATURES, args);
  210.       prefBranch.clearUserPref(PREF_EM_NEW_ADDONS_LIST);
  211.     }
  212.   },
  213.  
  214.   _onQuitRequest: function(aCancelQuit, aQuitType)
  215.   {
  216.     // If user has already dismissed quit request, then do nothing
  217.     if ((aCancelQuit instanceof Ci.nsISupportsPRBool) && aCancelQuit.data)
  218.       return;
  219.  
  220.     var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
  221.              getService(Ci.nsIWindowMediator);
  222.  
  223.     var windowcount = 0;
  224.     var pagecount = 0;
  225.     var browserEnum = wm.getEnumerator("navigator:browser");
  226.     while (browserEnum.hasMoreElements()) {
  227.       windowcount++;
  228.  
  229.       var browser = browserEnum.getNext();
  230.       var tabbrowser = browser.document.getElementById("content");
  231.       if (tabbrowser)
  232.         pagecount += tabbrowser.browsers.length;
  233.     }
  234.  
  235.     this._saveSession = false;
  236.     if (pagecount < 2)
  237.       return;
  238.  
  239.     if (aQuitType != "restart")
  240.       aQuitType = "quit";
  241.  
  242.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  243.                      getService(Ci.nsIPrefBranch);
  244.     var showPrompt = true;
  245.     try {
  246.       // browser.warnOnQuit is a hidden global boolean to override all quit prompts
  247.       // browser.warnOnRestart specifically covers app-initiated restarts where we restart the app
  248.       // browser.tabs.warnOnClose is the global "warn when closing multiple tabs" pref
  249.  
  250.       var sessionWillBeSaved = prefBranch.getIntPref("browser.startup.page") == 3 ||
  251.                                prefBranch.getBoolPref("browser.sessionstore.resume_session_once");
  252.       if (sessionWillBeSaved || !prefBranch.getBoolPref("browser.warnOnQuit"))
  253.         showPrompt = false;
  254.       else if (aQuitType == "restart")
  255.         showPrompt = prefBranch.getBoolPref("browser.warnOnRestart");
  256.       else
  257.         showPrompt = prefBranch.getBoolPref("browser.tabs.warnOnClose");
  258.     } catch (ex) {}
  259.  
  260.     if (!showPrompt)
  261.       return false;
  262.  
  263.     var buttonChoice = 0;
  264.     var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
  265.                         getService(Ci.nsIStringBundleService);
  266.     var quitBundle = bundleService.createBundle("chrome://browser/locale/quitDialog.properties");
  267.     var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
  268.  
  269.     var appName = brandBundle.GetStringFromName("brandShortName");
  270.     var quitDialogTitle = quitBundle.formatStringFromName(aQuitType + "DialogTitle",
  271.                                                             [appName], 1);
  272.  
  273.     var message;
  274.     if (aQuitType == "restart")
  275.       message = quitBundle.formatStringFromName("messageRestart",
  276.                                                 [appName], 1);
  277.     else if (windowcount == 1)
  278.       message = quitBundle.formatStringFromName("messageNoWindows",
  279.                                                 [appName], 1);
  280.     else
  281.       message = quitBundle.formatStringFromName("message",
  282.                                                 [appName], 1);
  283.  
  284.     var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
  285.                         getService(Ci.nsIPromptService);
  286.  
  287.     var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
  288.                 promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
  289.                 promptService.BUTTON_POS_0_DEFAULT;
  290.  
  291.     var neverAsk = {value:false};
  292.     var button0Title, button2Title;
  293.     var button1Title = quitBundle.GetStringFromName("cancelTitle");
  294.     var neverAskText = quitBundle.GetStringFromName("neverAsk");
  295.  
  296.     if (aQuitType == "restart")
  297.       button0Title = quitBundle.GetStringFromName("restartTitle");
  298.     else {
  299.       flags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2;
  300.       button0Title = quitBundle.GetStringFromName("saveTitle");
  301.       button2Title = quitBundle.GetStringFromName("quitTitle");
  302.     }
  303.  
  304.     buttonChoice = promptService.confirmEx(null, quitDialogTitle, message,
  305.                                  flags, button0Title, button1Title, button2Title,
  306.                                  neverAskText, neverAsk);
  307.  
  308.     switch (buttonChoice) {
  309.     case 2: // Quit
  310.       if (neverAsk.value)
  311.         prefBranch.setBoolPref("browser.tabs.warnOnClose", false);
  312.       break;
  313.     case 1: // Cancel
  314.       aCancelQuit.QueryInterface(Ci.nsISupportsPRBool);
  315.       aCancelQuit.data = true;
  316.       break;
  317.     case 0: // Save & Quit
  318.       this._saveSession = true;
  319.       if (neverAsk.value) {
  320.         if (aQuitType == "restart")
  321.           prefBranch.setBoolPref("browser.warnOnRestart", false);
  322.         else {
  323.           // always save state when shutting down
  324.           prefBranch.setIntPref("browser.startup.page", 3);
  325.         }
  326.       }
  327.       break;
  328.     }
  329.   },
  330.  
  331.   /*
  332.    * _shouldShowRights - Determines if the user should be shown the
  333.    * about:rights notification. The notification should *not* be shown if
  334.    * we've already shown the current version, or if the override pref says to
  335.    * never show it. The notification *should* be shown if it's never been seen
  336.    * before, if a newer version is available, or if the override pref says to
  337.    * always show it.
  338.    */
  339.   _shouldShowRights : function () {
  340.     // Look for an unconditional override pref. If set, do what it says.
  341.     // (true --> never show, false --> always show)
  342.     try {
  343.       return !this._prefs.getBoolPref("browser.rights.override");
  344.     } catch (e) { }
  345.     // Ditto, for the legacy EULA pref.
  346.     try {
  347.       return !this._prefs.getBoolPref("browser.EULA.override");
  348.     } catch (e) { }
  349.  
  350. //@line 391 "e:\fx19rel\WINNT_5.2_Depend\mozilla\browser\components\nsBrowserGlue.js"
  351.  
  352.     // Look to see if the user has seen the current version or not.
  353.     var currentVersion = this._prefs.getIntPref("browser.rights.version");
  354.     try {
  355.       return !this._prefs.getBoolPref("browser.rights." + currentVersion + ".shown");
  356.     } catch (e) { }
  357.  
  358.     // Legacy: If the user accepted a EULA, we won't annoy them with the
  359.     // equivalent about:rights page until the version changes.
  360.     try {
  361.       return !this._prefs.getBoolPref("browser.EULA." + currentVersion + ".accepted");
  362.     } catch (e) { }
  363.  
  364.     // We haven't shown the notification before, so do so now.
  365.     return true;
  366.   },
  367.  
  368.   _showRightsNotification : function () {
  369.     // Stick the notification onto the selected tab of the active browser window.
  370.     var win = this._getMostRecentBrowserWindow();
  371.     var browser = win.gBrowser; // for closure in notification bar callback
  372.     var notifyBox = browser.getNotificationBox();
  373.  
  374.     var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
  375.                         getService(Ci.nsIStringBundleService);
  376.     var brandBundle  = bundleService.createBundle("chrome://branding/locale/brand.properties");
  377.     var rightsBundle = bundleService.createBundle("chrome://browser/locale/aboutRights.properties");
  378.  
  379.     var buttonLabel     = rightsBundle.GetStringFromName("buttonLabel");
  380.     var buttonAccessKey = rightsBundle.GetStringFromName("buttonAccessKey");
  381.     var productName     = brandBundle.GetStringFromName("brandFullName");
  382.     var notifyText      = rightsBundle.formatStringFromName("notifyText", [productName], 1);
  383.     
  384.     var buttons = [
  385.                     {
  386.                       label:     buttonLabel,
  387.                       accessKey: buttonAccessKey,
  388.                       popup:     null,
  389.                       callback: function(aNotificationBar, aButton) {
  390.                         browser.selectedTab = browser.addTab("about:rights");
  391.                       }
  392.                     }
  393.                   ];
  394.  
  395.     // Set pref to indicate we've shown the notification.
  396.     var currentVersion = this._prefs.getIntPref("browser.rights.version");
  397.     this._prefs.setBoolPref("browser.rights." + currentVersion + ".shown", true);
  398.  
  399.     var box = notifyBox.appendNotification(notifyText, "about-rights", null, notifyBox.PRIORITY_INFO_LOW, buttons);
  400.     box.persistence = 3; // // arbitrary number, just so bar sticks around for a bit
  401.   },
  402.  
  403.   // returns the (cached) Sanitizer constructor
  404.   get Sanitizer() 
  405.   {
  406.     if(typeof(Sanitizer) != "function") { // we should dynamically load the script
  407.       Cc["@mozilla.org/moz/jssubscript-loader;1"].
  408.       getService(Ci.mozIJSSubScriptLoader).
  409.       loadSubScript("chrome://browser/content/sanitize.js", null);
  410.     }
  411.     return Sanitizer;
  412.   },
  413.  
  414.   _idleService: null,
  415.   get idleService() {
  416.     if (!this._idleService)
  417.       this._idleService = Cc["@mozilla.org/widget/idleservice;1"].
  418.                           getService(Ci.nsIIdleService);
  419.     return this._idleService;
  420.   },
  421.  
  422.   /**
  423.    * Initialize Places
  424.    * - imports the bookmarks html file if bookmarks datastore is empty
  425.    *
  426.    * These prefs are set by the backend services upon creation (or recreation)
  427.    * of the Places db:
  428.    * - browser.places.importBookmarksHTML
  429.    *   Set to false by the history service to indicate we need to re-import.
  430.    * - browser.places.smartBookmarksVersion
  431.    *   Set during HTML import to indicate that Smart Bookmarks were created.
  432.    *   Set to -1 to disable Smart Bookmarks creation.
  433.    *   Set to 0 to restore current Smart Bookmarks.
  434.    *
  435.    * These prefs are set up by the frontend:
  436.    * - browser.bookmarks.restore_default_bookmarks
  437.    *   Set to true by safe-mode dialog to indicate we must restore default
  438.    *   bookmarks.
  439.    */
  440.   _initPlaces: function bg__initPlaces() {
  441.     // we need to instantiate the history service before checking
  442.     // the browser.places.importBookmarksHTML pref, as
  443.     // nsNavHistory::ForceMigrateBookmarksDB() will set that pref
  444.     // if we need to force a migration (due to a schema change)
  445.     var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
  446.                   getService(Ci.nsINavHistoryService);
  447.  
  448.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  449.                      getService(Ci.nsIPrefBranch);
  450.  
  451.     var importBookmarks = false;
  452.     var restoreDefaultBookmarks = false;
  453.     try {
  454.       restoreDefaultBookmarks = prefBranch.getBoolPref("browser.bookmarks.restore_default_bookmarks");
  455.     } catch(ex) {}
  456.  
  457.     if (restoreDefaultBookmarks) {
  458.       // Ensure that we already have a bookmarks backup for today
  459.       this._archiveBookmarks();
  460.       // we will restore bookmarks from html
  461.       importBookmarks = true;
  462.     }
  463.     else {
  464.       try {
  465.         importBookmarks = prefBranch.getBoolPref("browser.places.importBookmarksHTML");
  466.       } catch(ex) {}
  467.     }
  468.  
  469.     if (!importBookmarks) {
  470.       // Call it here for Fx3 profiles created before the Places folder
  471.       // has been added, otherwise it's called during import.
  472.       this.ensurePlacesDefaultQueriesInitialized();
  473.     }
  474.     else {
  475.       // get latest backup
  476.       Cu.import("resource://gre/modules/utils.js");
  477.       var bookmarksFile = PlacesUtils.getMostRecentBackup();
  478.  
  479.       if (!restoreDefaultBookmarks &&
  480.           bookmarksFile && bookmarksFile.leafName.match("\.json$")) {
  481.         // restore a JSON backup
  482.         PlacesUtils.restoreBookmarksFromJSONFile(bookmarksFile);
  483.       }
  484.       else {
  485.         // if there's no JSON backup or we are restoring default bookmarks
  486.  
  487.         // ensurePlacesDefaultQueriesInitialized() is called by import.
  488.         prefBranch.setIntPref("browser.places.smartBookmarksVersion", 0);
  489.  
  490.         var dirService = Cc["@mozilla.org/file/directory_service;1"].
  491.                          getService(Ci.nsIProperties);
  492.  
  493.         var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
  494.         if (restoreDefaultBookmarks || !bookmarksFile.exists()) {
  495.           // get bookmarks.html file from default profile folder
  496.           bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
  497.           bookmarksFile.append("bookmarks.html");
  498.         }
  499.  
  500.         // import the file
  501.         try {
  502.           var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
  503.                          getService(Ci.nsIPlacesImportExportService);
  504.           importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
  505.         } catch (err) {
  506.           // Report the error, but ignore it.
  507.           Cu.reportError(err);
  508.         }
  509.         prefBranch.setBoolPref("browser.places.importBookmarksHTML", false);
  510.         if (restoreDefaultBookmarks)
  511.           prefBranch.setBoolPref("browser.bookmarks.restore_default_bookmarks",
  512.                                  false);
  513.       }
  514.     }
  515.  
  516.     // Initialize bookmark archiving on idle.
  517.     // Once a day, either on idle or shutdown, bookmarks are backed up.
  518.     this.idleService.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
  519.   },
  520.  
  521.   /**
  522.    * Places shut-down tasks
  523.    * - back up and archive bookmarks
  524.    * - export bookmarks as HTML, if so configured
  525.    *
  526.    * Note: quit-application-granted notification is received twice
  527.    *       so replace this method with a no-op when first called.
  528.    */
  529.   _shutdownPlaces: function bg__shutdownPlaces() {
  530.     // Backup and archive Places bookmarks.
  531.     this._archiveBookmarks();
  532.  
  533.     // Backup bookmarks to bookmarks.html to support apps that depend
  534.     // on the legacy format.
  535.     var prefs = Cc["@mozilla.org/preferences-service;1"].
  536.                 getService(Ci.nsIPrefBranch);
  537.     var autoExportHTML = false;
  538.     try {
  539.       autoExportHTML = prefs.getBoolPref("browser.bookmarks.autoExportHTML");
  540.     } catch(ex) {
  541.       Components.utils.reportError(ex);
  542.     }
  543.  
  544.     if (autoExportHTML) {
  545.       Cc["@mozilla.org/browser/places/import-export-service;1"].
  546.         getService(Ci.nsIPlacesImportExportService).
  547.         backupBookmarksFile();
  548.     }
  549.   },
  550.  
  551.   /**
  552.    * Back up and archive bookmarks
  553.    */
  554.   _archiveBookmarks: function nsBrowserGlue__archiveBookmarks() {
  555.     Cu.import("resource://gre/modules/utils.js");
  556.  
  557.     var lastBackup = PlacesUtils.getMostRecentBackup();
  558.  
  559.     // Backup bookmarks if there aren't any backups or 
  560.     // they haven't been backed up in the last 24 hrs.
  561.     if (!lastBackup ||
  562.         Date.now() - lastBackup.lastModifiedTime > BOOKMARKS_ARCHIVE_INTERVAL) {
  563.       var maxBackups = 5;
  564.       var prefs = Cc["@mozilla.org/preferences-service;1"].
  565.                   getService(Ci.nsIPrefBranch);
  566.       try {
  567.         maxBackups = prefs.getIntPref("browser.bookmarks.max_backups");
  568.       } catch(ex) {}
  569.  
  570.       PlacesUtils.archiveBookmarksFile(maxBackups, false /* don't force */);
  571.     }
  572.   },
  573.  
  574.   _migrateUI: function bg__migrateUI() {
  575.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
  576.  
  577.     var migration = 0;
  578.     try {
  579.       migration = prefBranch.getIntPref("browser.migration.version");
  580.     } catch(ex) {}
  581.  
  582.     if (migration == 0) {
  583.       // this code should always migrate pre-FF3 profiles to the current UI state
  584.  
  585.       // grab the localstore.rdf and make changes needed for new UI
  586.       this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
  587.       this._dataSource = this._rdf.GetDataSource("rdf:local-store");
  588.       this._dirty = false;
  589.  
  590.       let currentsetResource = this._rdf.GetResource("currentset");
  591.       let toolbars = ["nav-bar", "toolbar-menubar", "PersonalToolbar"];
  592.       for (let i = 0; i < toolbars.length; i++) {
  593.         let toolbar = this._rdf.GetResource("chrome://browser/content/browser.xul#" + toolbars[i]);
  594.         let currentset = this._getPersist(toolbar, currentsetResource);
  595.         if (!currentset) {
  596.           // toolbar isn't customized
  597.           if (i == 0)
  598.             // new button is in the defaultset, nothing to migrate
  599.             break;
  600.           continue;
  601.         }
  602.         if (/(?:^|,)unified-back-forward-button(?:$|,)/.test(currentset))
  603.           // new button is already there, nothing to migrate
  604.           break;
  605.         if (/(?:^|,)back-button(?:$|,)/.test(currentset)) {
  606.           let newset = currentset.replace(/(^|,)back-button($|,)/,
  607.                                           "$1unified-back-forward-button,back-button$2")
  608.           this._setPersist(toolbar, currentsetResource, newset);
  609.           // done migrating
  610.           break;
  611.         }
  612.       }
  613.  
  614.       // force the RDF to be saved
  615.       if (this._dirty)
  616.         this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
  617.  
  618.       // free up the RDF service
  619.       this._rdf = null;
  620.       this._dataSource = null;
  621.  
  622.       // update the migration version
  623.       prefBranch.setIntPref("browser.migration.version", 1);
  624.     }
  625.   },
  626.  
  627.   _getPersist: function bg__getPersist(aSource, aProperty) {
  628.     var target = this._dataSource.GetTarget(aSource, aProperty, true);
  629.     if (target instanceof Ci.nsIRDFLiteral)
  630.       return target.Value;
  631.     return null;
  632.   },
  633.  
  634.   _setPersist: function bg__setPersist(aSource, aProperty, aTarget) {
  635.     this._dirty = true;
  636.     try {
  637.       var oldTarget = this._dataSource.GetTarget(aSource, aProperty, true);
  638.       if (oldTarget) {
  639.         if (aTarget)
  640.           this._dataSource.Change(aSource, aProperty, oldTarget, this._rdf.GetLiteral(aTarget));
  641.         else
  642.           this._dataSource.Unassert(aSource, aProperty, oldTarget);
  643.       }
  644.       else {
  645.         this._dataSource.Assert(aSource, aProperty, this._rdf.GetLiteral(aTarget), true);
  646.       }
  647.     }
  648.     catch(ex) {}
  649.   },
  650.  
  651.   // ------------------------------
  652.   // public nsIBrowserGlue members
  653.   // ------------------------------
  654.   
  655.   sanitize: function(aParentWindow) 
  656.   {
  657.     this.Sanitizer.sanitize(aParentWindow);
  658.   },
  659.  
  660.   ensurePlacesDefaultQueriesInitialized: function() {
  661.     const SMART_BOOKMARKS_VERSION = 1;
  662.     const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
  663.     const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
  664.  
  665.     // XXX should this be a pref?  see bug #399268
  666.     const MAX_RESULTS = 10;
  667.  
  668.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  669.                      getService(Ci.nsIPrefBranch);
  670.  
  671.     // get current smart bookmarks version
  672.     // By default, if the pref is not set up, we must create Smart Bookmarks
  673.     var smartBookmarksCurrentVersion = 0;
  674.     try {
  675.       smartBookmarksCurrentVersion = prefBranch.getIntPref(SMART_BOOKMARKS_PREF);
  676.     } catch(ex) {}
  677.  
  678.     // bail out if we don't have to create or update Smart Bookmarks
  679.     if (smartBookmarksCurrentVersion == -1 ||
  680.         smartBookmarksCurrentVersion >= SMART_BOOKMARKS_VERSION)
  681.       return;
  682.  
  683.     var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
  684.                 getService(Ci.nsINavBookmarksService);
  685.     var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].
  686.                   getService(Ci.nsIAnnotationService);
  687.  
  688.     var callback = {
  689.       _placesBundle: Cc["@mozilla.org/intl/stringbundle;1"].
  690.                      getService(Ci.nsIStringBundleService).
  691.                      createBundle("chrome://browser/locale/places/places.properties"),
  692.  
  693.       _uri: function(aSpec) {
  694.         return Cc["@mozilla.org/network/io-service;1"].
  695.                getService(Ci.nsIIOService).
  696.                newURI(aSpec, null, null);
  697.       },
  698.  
  699.       runBatched: function() {
  700.         var smartBookmarks = [];
  701.         var bookmarksMenuIndex = 0;
  702.         var bookmarksToolbarIndex = 0;
  703.  
  704.         // MOST VISITED
  705.         var smart = {queryId: "MostVisited", // don't change this
  706.                      itemId: null,
  707.                      title: this._placesBundle.GetStringFromName("mostVisitedTitle"),
  708.                      uri: this._uri("place:queryType=" +
  709.                                     Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY +
  710.                                     "&sort=" +
  711.                                     Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
  712.                                     "&maxResults=" + MAX_RESULTS),
  713.                      parent: bmsvc.toolbarFolder,
  714.                      position: bookmarksToolbarIndex++};
  715.         smartBookmarks.push(smart);
  716.  
  717.         // RECENTLY BOOKMARKED
  718.         smart = {queryId: "RecentlyBookmarked", // don't change this
  719.                  itemId: null,
  720.                  title: this._placesBundle.GetStringFromName("recentlyBookmarkedTitle"),
  721.                  uri: this._uri("place:folder=BOOKMARKS_MENU" +
  722.                                 "&folder=UNFILED_BOOKMARKS" +
  723.                                 "&folder=TOOLBAR" +
  724.                                 "&queryType=" +
  725.                                 Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
  726.                                 "&sort=" +
  727.                                 Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
  728.                                 "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
  729.                                 "&maxResults=" + MAX_RESULTS +
  730.                                 "&excludeQueries=1"),
  731.                  parent: bmsvc.bookmarksMenuFolder,
  732.                  position: bookmarksMenuIndex++};
  733.         smartBookmarks.push(smart);
  734.  
  735.         // RECENT TAGS
  736.         smart = {queryId: "RecentTags", // don't change this
  737.                  itemId: null,
  738.                  title: this._placesBundle.GetStringFromName("recentTagsTitle"),
  739.                  uri: this._uri("place:"+
  740.                     "type=" +
  741.                     Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
  742.                     "&sort=" +
  743.                     Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
  744.                     "&maxResults=" + MAX_RESULTS),
  745.                  parent: bmsvc.bookmarksMenuFolder,
  746.                  position: bookmarksMenuIndex++};
  747.         smartBookmarks.push(smart);
  748.  
  749.         var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {});
  750.         // set current itemId, parent and position if Smart Bookmark exists
  751.         for each(var itemId in smartBookmarkItemIds) {
  752.           var queryId = annosvc.getItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
  753.           for (var i = 0; i < smartBookmarks.length; i++){
  754.             if (smartBookmarks[i].queryId == queryId) {
  755.               smartBookmarks[i].itemId = itemId;
  756.               smartBookmarks[i].parent = bmsvc.getFolderIdForItem(itemId);
  757.               smartBookmarks[i].position = bmsvc.getItemIndex(itemId);
  758.               // remove current item, since it will be replaced
  759.               bmsvc.removeItem(itemId);
  760.               break;
  761.             }
  762.             // We don't remove old Smart Bookmarks because user could still
  763.             // find them useful, or could have personalized them.
  764.             // Instead we remove the Smart Bookmark annotation.
  765.             if (i == smartBookmarks.length - 1)
  766.               annosvc.removeItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
  767.           }
  768.         }
  769.  
  770.         // create smart bookmarks
  771.         for each(var smartBookmark in smartBookmarks) {
  772.           smartBookmark.itemId = bmsvc.insertBookmark(smartBookmark.parent,
  773.                                                       smartBookmark.uri,
  774.                                                       smartBookmark.position,
  775.                                                       smartBookmark.title);
  776.           annosvc.setItemAnnotation(smartBookmark.itemId,
  777.                                     SMART_BOOKMARKS_ANNO, smartBookmark.queryId,
  778.                                     0, annosvc.EXPIRE_NEVER);
  779.         }
  780.         
  781.         // If we are creating all Smart Bookmarks from ground up, add a
  782.         // separator below them in the bookmarks menu.
  783.         if (smartBookmarkItemIds.length == 0)
  784.           bmsvc.insertSeparator(bmsvc.bookmarksMenuFolder, bookmarksMenuIndex);
  785.       }
  786.     };
  787.  
  788.     try {
  789.       bmsvc.runInBatchMode(callback, null);
  790.     }
  791.     catch(ex) {
  792.       Components.utils.reportError(ex);
  793.     }
  794.     finally {
  795.       prefBranch.setIntPref(SMART_BOOKMARKS_PREF, SMART_BOOKMARKS_VERSION);
  796.       prefBranch.QueryInterface(Ci.nsIPrefService).savePrefFile(null);
  797.     }
  798.   },
  799.  
  800. //@line 848 "e:\fx19rel\WINNT_5.2_Depend\mozilla\browser\components\nsBrowserGlue.js"
  801.  
  802.   // this returns the most recent non-popup browser window
  803.   _getMostRecentBrowserWindow : function ()
  804.   {
  805.     var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
  806.              getService(Components.interfaces.nsIWindowMediator);
  807.  
  808. //@line 870 "e:\fx19rel\WINNT_5.2_Depend\mozilla\browser\components\nsBrowserGlue.js"
  809.     var windowList = wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
  810.     if (!windowList.hasMoreElements())
  811.       return null;
  812.  
  813.     var win = windowList.getNext();
  814.     while (win.document.documentElement.getAttribute("chromehidden")) {
  815.       if (!windowList.hasMoreElements())
  816.         return null;
  817.  
  818.       win = windowList.getNext();
  819.     }
  820. //@line 882 "e:\fx19rel\WINNT_5.2_Depend\mozilla\browser\components\nsBrowserGlue.js"
  821.  
  822.     return win;
  823.   },
  824.  
  825.   // for XPCOM
  826.   classDescription: "Firefox Browser Glue Service",
  827.   classID:          Components.ID("{eab9012e-5f74-4cbc-b2b5-a590235513cc}"),
  828.   contractID:       "@mozilla.org/browser/browserglue;1",
  829.  
  830.   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
  831.                                          Ci.nsISupportsWeakReference,
  832.                                          Ci.nsIBrowserGlue]),
  833.  
  834.   // redefine the default factory for XPCOMUtils
  835.   _xpcom_factory: BrowserGlueServiceFactory,
  836.  
  837.   // get this contractID registered for certain categories via XPCOMUtils
  838.   _xpcom_categories: [
  839.     // make BrowserGlue a startup observer
  840.     { category: "app-startup", service: true }
  841.   ]
  842. }
  843.  
  844. //module initialization
  845. function NSGetModule(aCompMgr, aFileSpec) {
  846.   return XPCOMUtils.generateModule([BrowserGlue]);
  847. }
  848.  
  849.